package controller

import (
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
	uuid "github.com/satori/go.uuid"
	alipay "github.com/smartwalle/alipay/v3"
	"myproject/model"
	"myproject/schemas"
	"myproject/utils"
	"net/http"
	"strconv"
	"time"
)

func Zhi(zhiPath *gin.RouterGroup) {
	//获取支付宝地址
	zhiPath.Use().GET("/getpayurl", getpayurl)
	//回调接口
	zhiPath.Use().GET("/callback", callback)
	//生成uuid
	zhiPath.Use().GET("/Getuuid", getuuid)
	//建立连接
	zhiPath.Use().GET("/socketConn", socketConn)
	//发标
	zhiPath.Use().POST("/sendTargetLand", sendTargetLand)
	//要审核地
	zhiPath.Use().GET("/AllTask", allTask)
	//用户的总额
	zhiPath.Use().GET("/jin", jin)
	// 获取发标的列表
	zhiPath.Use().GET("/sendTargetLands", sendTargetLands)
	//投资
	zhiPath.Use().POST("/addBids", AddBids)

	zhiPath.Use().GET("/KefnConn", kefuConn)
	//添加订阅
	//zhiPath.Use().POST("/addSubscribe", addSubscribe)
}

// 获取支付宝地址
func getpayurl(c *gin.Context) {
	utils.Init()
	money := c.Query("money")
	id := c.Query("id")
	var p = alipay.TradePagePay{}
	p.NotifyURL = "http://localhost:8000/zhi/callback?" + money + "id?" + id
	p.ReturnURL = "http://localhost:8000/zhi/callback?" + money + "id?" + id
	p.Subject = "要充值"
	number := utils.RandInt(10000, 99999)
	p.OutTradeNo = strconv.Itoa(number)
	p.TotalAmount = money
	p.ProductCode = "FAST_INSTANT_TRADE_PAY"

	url, err := utils.Client.TradePagePay(p)
	if err != nil {
		c.JSON(200, gin.H{
			"code": 20010,
			"mes":  "获取",
		})
		return
	}

	//fmt.Println(url)

	urll := url.Scheme + "://" + url.Host + url.Path + "?" + url.RawQuery
	c.JSON(200, gin.H{
		"code": 200,
		"url":  urll,
	})
}

// 支付宝回调接口
func callback(c *gin.Context) {
	//id := c.Query("uid")
	//难签
	order, err := utils.Client.GetTradeNotification(c.Request)
	alipay.AckNotification(c.Writer) // 确认收到通知消息
	fmt.Println(err, order)
	if order == nil {
		fmt.Println("验证失败")
	} else {
		fmt.Println(order)
		//var uid int
		//sql := "insert into Recharge (money, Userid) values (?,?)"
		//model.DB.Exec(sql,).Scan(&uid)
	}

}

// 生成uuid
func getuuid(c *gin.Context) {
	r := utils.RedisPool
	Uid := c.Query("uid")
	id := uuid.NewV4()
	ids := id.String()
	r.Setex(ids, 30, Uid)
	c.JSON(200, gin.H{
		"ids":  ids,
		"code": "10025",
	})
}

// 发布标地
func sendTargetLand(c *gin.Context) {
	r := utils.RedisPool
	var Target schemas.Target
	_ = c.Bind(&Target)
	uuidcode := r.Get(Target.Uuid)
	if uuidcode == "" {
		c.JSON(200, gin.H{
			"code": 10022,
			"msg":  "提交失败，重新提交",
		})
		return
	}
	r.StrDel(Target.Uuid)
	snow := strconv.FormatInt((snowflake()), 10)
	snows, _ := strconv.Atoi(snow)
	code := snows % 3
	var table string = "target_land" + fmt.Sprint(code)
	sql := fmt.Sprintf("INSERT INTO %s (code,Userid,money,remaining_amount) values (?,?,?,?)", table)
	err := model.DB.Exec(sql, snow, Target.Userid, Target.Money, Target.Money)
	fmt.Println(err)
	if err.Error != nil {
		fmt.Println(err.Error)
	}
	num := code%5 + 1
	snowcode, _ := strconv.Atoi(snow)
	r.ListAdd("snowcode", snowcode)
	utils.AuditTask()
	c.JSON(200, gin.H{
		"code": 200,
		"msg":  "发标成功",
		"num":  num,
	})
}

// 雪花算法id
func snowflake() int64 {
	worker, err := utils.NewWorker(0)
	if err != nil {
		fmt.Println(err)
	}
	id := worker.NextId()
	fmt.Println(id)
	return id

}

var (
	upgrader = websocket.Upgrader{
		ReadBufferSize:   1024,
		WriteBufferSize:  1024,
		CheckOrigin:      func(r *http.Request) bool { return true },
		HandshakeTimeout: time.Duration(time.Second * 5),
	}
)

// 定义用户结构体
type Userinfo struct {
	Id   string
	Name string
}

// 在线用户列表
var Userlist []*Userinfo

// 建立websoket链接
func kefuConn(c *gin.Context) {
	id := c.Query("id")
	//建立连接
	conn, _ := upgrader.Upgrade(c.Writer, c.Request, nil)
	//保存连接
	utils.SocketLink[id] = conn
	//删除user1
	delete(utils.SocketLink, "1")
	//加入用户在线列表中
	if id != "kefu" {
		userinfo := &Userinfo{
			Id:   id,
			Name: "用户" + id,
		}
		Userlist = append(Userlist, userinfo)
	}

	//接收消息转发
	for {
		msgType, msgData, _ := conn.ReadMessage()

		if id == "kefu" {
			//读取消息，转成Json
			var mesMap = make(map[string]string)
			json.Unmarshal([]byte(string(msgData)), &mesMap)

			userid := mesMap["userid"]
			//判断用户是否已经连接
			userconn, ok := utils.SocketLink[userid]
			if ok {
				userconn.WriteMessage(msgType, []byte(mesMap["mes"]))
			} else {
				fmt.Println("&&&&")
				//如果下线存在mq
				myqueue := "socketmes" + userid
				//ListAdd
				// utils.RedisPool.ListGetAll(myqueue)
				intes, _ := strconv.Atoi(mesMap["mes"])
				utils.RedisPool.ListAdd(myqueue, intes)

			}

		} else {
			//用户给客服发信息
			var returnData = make(map[string]interface{})
			returnData["message"] = string(msgData)
			returnData["userlist"] = Userlist
			ulist, _ := json.Marshal(returnData)
			utils.SocketLink["kefu"].WriteMessage(msgType, ulist)
		}
	}
}

// 建立连接
func socketConn(c *gin.Context) {
	kefuid := c.Query("id")
	//建立连接
	conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
	if err != nil {
		fmt.Println(err, "Upgrade failed")
		c.JSON(200, gin.H{
			"code": 10010,
			"mes":  "连接错误",
		})
		return
	}
	//存储在map中
	utils.SocketLink[kefuid] = conn
}

func SocketSend() {
	for {
		//从客户端获取消息
		//mes := c.Query("mes")
		//kefuid := c.Query("id")
		//从map中获取连接
		//conn := utils.SocketLink[kefuid]
		if conn, ok := utils.SocketLink["kefuid"]; ok {
			//发送消息给客户端
			conn.WriteMessage(1, []byte("0"))
		} else {
			fmt.Println("Key Not Found", conn)
		}

		time.Sleep(time.Second * 10)
	}
}

// 要审核的
func allTask(c *gin.Context) {
	TargetTask := schemas.TargetTask{}
	var lists []interface{}
	id := c.Query("id")
	auditid := "audit" + id
	r := utils.RedisPool
	res := r.ListGetAll2(auditid)
	for _, i := range res {
		num, _ := strconv.Atoi(i)
		table := "target_land" + strconv.Itoa(num%3)
		sql := fmt.Sprintf("SELECT * from %s where code='%s'", table, i)
		model.DB.Raw(sql).Scan(&TargetTask)
		lists = append(lists, TargetTask)
	}
	c.JSON(200, gin.H{
		"list": lists,
	})
}

// 用户金额
func jin(c *gin.Context) {
	var list []schemas.List
	ID := c.Query("id")
	sql := "select tmoney,beoverdue_money from users where id=?"
	model.DB.Raw(sql, ID).Scan(&list)

	c.JSON(200, gin.H{
		"code": "200",
		"msg":  "获取成功",
		"data": list,
	})
}

// 获取发标的列表
func sendTargetLands(c *gin.Context) {
	var list []schemas.TargetLand
	sql := "select * from target_land0 union select * from target_land1 union select * from target_land2"
	model.DB.Raw(sql).Scan(&list)

	c.JSON(200, gin.H{
		"code": "200",
		"msg":  "获取成功",
		"data": list,
	})
}

//// 添加订阅
//func addSubscribe(c *gin.Context) {
//	var bes schemas.Ding
//	_ = c.Bind(&bes)
//	sql := "INSERT INTO subscribes (name,status) VALUES (?,?)"
//	model.DB.Exec(sql, bes.Na, bes.Status)
//	c.JSON(200, gin.H{
//		"code": "200",
//		"msg":  "订阅成功",
//	})
//}

// 投资
func AddBids(c *gin.Context) {
	bidInfo := schemas.Bid{}
	_ = c.Bind(&bidInfo)
	var user model.User
	sql := "select * from users where id=?"
	uid, _ := strconv.Atoi(bidInfo.Id)
	model.DB.Raw(sql, uid).Scan(&user)
	money, _ := strconv.Atoi(bidInfo.Money)
	if user.Tmoney < float32(money) {
		c.JSON(200, gin.H{
			"code": 10020,
			"msg":  "钱不够,重新投",
		})
		return
	}

	code1 := snowflake()
	sql1 := "insert into bids(userid,code,money,status,remaining_amount)  values (?,?,?,2,?)"
	res := model.DB.Exec(sql1, bidInfo.Id, code1, bidInfo.Money, user.Tmoney-float32(money))
	if res.Error != nil {
		fmt.Println(res.Error)
		c.JSON(200, gin.H{
			"code": 10021,
			"msg":  "投资失败",
		})
		return
	}

	var targetLand schemas.TargetLand
	code, _ := strconv.Atoi(bidInfo.TargetLandCode)
	table := "target_land" + strconv.Itoa(code%3)
	fmt.Println(table, "???????fsdsf")
	// 查询标的记录
	sql3 := fmt.Sprintf("select * from %s where Code='%s'", table, bidInfo.TargetLandCode)
	fmt.Println(sql3)
	err3 := model.DB.Raw(sql3).Scan(&targetLand)
	if err3.Error != nil {
		fmt.Println(err3, "???????????????????????????????????")
		return
	}
	add, _ := strconv.Atoi(bidInfo.Money)
	if int(targetLand.RemainingAmount) < add {
		c.JSON(200, gin.H{
			"code": 400,
			"msg":  "输入金额超过借款金额",
		})
		return
	}
	// 写入投资记录表
	sql2 := "insert into Targetland_Bids(Target_Land,Bid,Money,Status) values (?,?,?,?) "
	err := model.DB.Exec(sql2, bidInfo.TargetLandCode, code, money, 2)
	if err.Error != nil {
		fmt.Println(err.Error)
		c.JSON(200, gin.H{
			"code": 10021,
			"msg":  "投资表添加失败",
		})
		return
	}
	// 修改标地表的剩余金额
	surplus := int(targetLand.RemainingAmount) - money
	fmt.Println(surplus)
	sql4 := fmt.Sprintf("update %s set Remaining_Amount=%d,status=2 where code='%s'", table, surplus, bidInfo.TargetLandCode)
	res4 := model.DB.Exec(sql4)
	if res4.Error != nil {
		fmt.Println(res4.Error)
		c.JSON(200, gin.H{
			"code": 400,
			"msg":  "失败",
		})
		return
	}
	// 更改当前登录用户的金额
	//用户投资之后的钱
	nowMoney := int(user.Tmoney) - money
	// 冻结金额基础上继续加
	freeze, _ := strconv.ParseFloat(bidInfo.Money, 32)
	newfreeze := user.BeoverdueMoney + float32(freeze)
	sql5 := "update users set Beoverdue_Money=?,tmoney=? where id=?"
	res5 := model.DB.Exec(sql5, newfreeze, nowMoney, uid)
	if res5.Error != nil {
		fmt.Println(res4.Error)
		c.JSON(200, gin.H{
			"code": 400,
			"msg":  "失败",
		})
		return
	}
	c.JSON(200, gin.H{
		"code": "200",
		"msg":  "投资成功",
	})
}
